#!/usr/bin/python
# -*- coding: utf-8 -*-
# import sys
# import binascii
# import os
from threading import Thread
# import string
import socket
import struct
import time
from os import stat
from functools import partial
import platform
from tkinter import messagebox
def program__wr_mini_thread(*args):
    root,strvar_Progress,button_per,my_ip, dst_ip,filename, processbar,hw_type,all_pb,_all_strvar_Progress = args
    for _ip in dst_ip:
        button_per.set("IP:{} 正在进行".format(_ip))
        ret = program_wr_mini(root,strvar_Progress,my_ip, _ip, filename, processbar,hw_type)
        if ret == 0:
            all_pb["value"] = (dst_ip.index(_ip)+1)/len(dst_ip) * 100
            _all_strvar_Progress.set("{}/{}".format(dst_ip.index(_ip)+1, len(dst_ip)))  
            button_per.set("IP:{} 已完成".format(_ip))
            time.sleep(3)
        else:
            return ret
    return 0
def program_wr_mini(root,button,my_ip, dst_ip, filename, processbar,hw_type):
    # persent = 0
    # for i in range(1000):
    #     persent = persent + 0.1
    #     processbar['value'] = persent
    # return 0

    # py_ver=platform.python_version()
    # print("my_ip is %s dstip is %s filename is %s"%(my_ip, dst_ip, filename))
    ##    if int(platform.python_version().split('.')[0]) > 2:
    ##        print("Please use python 2.x")
    ##        return 0
    processbar['value'] = 1
    button.set('1%')
    root.update()

    UDP_TX_PORT = 71
    UDP_RX_PORT = 1555

    magicUDP = struct.pack('4c', 'b'.encode('ascii'), 'e'.encode('ascii'), 'e'.encode('ascii'), 'f'.encode('ascii'))
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind((my_ip, UDP_RX_PORT))

    flash_erase_type = struct.pack('!I', 0x0000ffff)
    flash_write_type = struct.pack('!I', 0x00000000)
    flash_read_type = struct.pack('!I', 0x00000001)
    reg_read_type = struct.pack('!I', 0x00000011)
    reg_write_type = struct.pack('!I', 0x00000010)

    err_udp_checksum = 0xff
    err_magic_data = 0xfe
    err_reply_loss = 0xfd
    err_operation_type = 0xfc

    if hw_type == 2:
        start_addr = 0x003B0000
    else:
        start_addr = 0x00170000
    flash_start_addr = struct.pack('!I', start_addr)
    if hw_type == 2:
        flash_erase_size = struct.pack('!I', 0x003B0000)
    else:
        flash_erase_size = struct.pack('!I', 0x00170000)


    flash_size = struct.pack('!I', 256)
    reg_addr = struct.pack('!I', 0x20708)
    reg_bytes_count = struct.pack('!I', 0x04)
    reg_write_bytes = struct.pack('!I', 0x0b000044)

    # check connection first
    MESSAGE = magicUDP
    MESSAGE += reg_read_type + reg_addr + reg_bytes_count
    print("check connection")
    sock.sendto(MESSAGE, (dst_ip, UDP_TX_PORT))
    sock.settimeout(5.0)
    try:
        recv = sock.recv(1024)
        if (recv[0:8] == bytes.fromhex('6265656600000011')):
            print("connection successed!")
    except socket.timeout as e:
        print("{} connection failed!".format(sock.getpeername()))
        sock.close()
        return 1
    processbar['value'] = 3
    button.set('3%')
    root.update()

    MESSAGE = magicUDP
    MESSAGE += flash_erase_type + flash_start_addr + flash_erase_size
    print("Flash Erase start")
    sock.sendto(MESSAGE, (dst_ip, UDP_TX_PORT))
    sock.settimeout(60.0)
    processbar['value'] = 5
    button.set('5%')
    root.update()
    try:
        recv = sock.recv(1024)
        print("Flash Erase done!")
    except socket.timeout as e:
        print("Flash erase timeout!")
        sock.close()
        return 2
        # os._exit(0)

    processbar['value'] = 10
    button.set('10%')
    root.update()
    filesize = stat(filename).st_size

    time.sleep(1)
    f = open(filename, 'rb')
    print("Complete:")
    count = 0
    for dat in iter(partial(f.read, 256), b''):
        cur_package_done = 0
        MESSAGE = magicUDP
        i = 0
        flash_start_addr = struct.pack('!I', start_addr)
        MESSAGE += flash_write_type + flash_start_addr + flash_size
        while i < 256:
            if i < len(dat) - 1:
                MESSAGE += dat[i].to_bytes(1, 'little')
                MESSAGE += dat[i + 1].to_bytes(1, 'little')
            else:
                MESSAGE += struct.pack("!2x")
            i += 2
        los_package_cnt = 0
        while cur_package_done == 0:
            sock.sendto(MESSAGE, (dst_ip, UDP_TX_PORT))
            sock.settimeout(1)
            if los_package_cnt >20:
                sock.close()
                return -1
            try:
                recv = sock.recv(1024)
                if (recv[12] == struct.pack('!B', err_udp_checksum)):
                    sock.sendto(MESSAGE, (dst_ip, UDP_TX_PORT))
                    print("udp checksum err!\n", los_package_cnt)
                elif (recv[12] == struct.pack('!B', err_reply_loss)):
                    print("reply loss err!\n", los_package_cnt)
                    cur_package_done = 1
                else:
                    cur_package_done = 1
            except socket.timeout as e:
                los_package_cnt = los_package_cnt + 1
                # print("Packets lose!\n",los_package_cnt)

        start_addr += 256
        if ((count % 256) == 0):
            print("...%d" % (count * 256 / filesize * 100))
        count += 1
        # print("...%d %d" % (start_addr,(start_addr / filesize * 85)))

        if hw_type == 2:
            persent = 10 + (start_addr-0x3B0000) / filesize * 90
        else:
            persent = 10 + (start_addr-0x170000) / filesize * 90

        processbar['value'] = persent
        button.set(str(int(persent)) + '%')
        root.update()

    print("Program Success!")
    processbar['value'] = 100
    root.update()
    sock.close()
    return 0

def testfunc(root,button,my_ip, dst_ip, filename, processbar):

    processbar['value'] = 0
    n = 0
    for i in range(20):
        n = n + 5
        processbar['value'] = n
        button.set(str(n)+'%')
        time.sleep(0.1)
        root.update()
        print(n)
    return 0

